/****************************************************************************
 *
 * Copyright (C) 2003-2010 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.dataset.netsensor;

import java.sql.Date;
import java.sql.Timestamp;

import nfse.NetFSE;
import nfse.NetFSERecord;
import nfse.NetFSEUtil;
import nfse.gui.record.FlexRecordField;
import nfse.gui.server.GUIRecordFactory;
import nfse.gui.server.RecordBuilderUtil;

public class NetSensorSessionFactory extends GUIRecordFactory<NetSensorSession> {

    public boolean SET_TO_CURRENT = true;

    public NetSensorSessionFactory() {
        builder = new RecordBuilderUtil();
        builder.addColumn(null, "ID", RecordBuilderUtil.BIGINT);
        RecordBuilderUtil.SQLField field = builder.addColumn("Start TS", "startts", RecordBuilderUtil.TIMESTAMP);
        field = builder.addColumn("End TS", "endts", RecordBuilderUtil.TIMESTAMP);
        field = builder.addColumn("Src IP", "srcip", RecordBuilderUtil.INET);
        field = builder.addColumn("Src Port", "srcport", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PORT);
        field = builder.addColumn("Dst IP", "dstip", RecordBuilderUtil.INET);
        field = builder.addColumn("Dst Port", "dstport", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PORT);
        field = builder.addColumn("Src Bytes", "srcbytes", RecordBuilderUtil.BIGINT);
        field = builder.addColumn("Dst Bytes", "dstbytes", RecordBuilderUtil.BIGINT);
        field = builder.addColumn("App Protocol", "appprotocol", RecordBuilderUtil.VARCHAR, 50);
        field = builder.addColumn("Protocol", "protocol", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PROTOCOL);
        field = builder.addColumn("Duration", "duration", RecordBuilderUtil.FLOAT);
        field = builder.addColumn("State", "state", RecordBuilderUtil.VARCHAR, 6);
        field = builder.addColumn("Flags", "flags", RecordBuilderUtil.VARCHAR, 5);
        field = builder.addColumn("Tag", "tag", RecordBuilderUtil.VARCHAR, 50);
        field = builder.addColumn("Init", "init", RecordBuilderUtil.VARCHAR, 10);
    }

    @Override
    protected void setValues(NetSensorSession record, int id) {
        int idx = -1;
        builder.setFieldValue(++idx, "" + id);
        builder.setFieldValue(++idx, "" + record.getStartTS());
        builder.setFieldValue(++idx, "" + record.getEndTS());
        builder.setFieldValue(++idx, "" + record.getSrcAddr());
        builder.setFieldValue(++idx, "" + record.srcPort);
        builder.setFieldValue(++idx, "" + record.getDstAddr());
        builder.setFieldValue(++idx, "" + record.dstPort);
        builder.setFieldValue(++idx, "" + record.srcBytes);
        builder.setFieldValue(++idx, "" + record.dstBytes);
        builder.setFieldValue(++idx, "" + record.appProto);
        builder.setFieldValue(++idx, "" + record.proto);
        builder.setFieldValue(++idx, "" + record.duration);
        builder.setFieldValue(++idx, "" + record.state);
        builder.setFieldValue(++idx, "" + record.flags);
        builder.setFieldValue(++idx, "" + record.tag);
        builder.setFieldValue(++idx, "" + record.isInit());

    }

    @Override
    public NetFSERecord generate(String line, int sensor) throws Exception {
        // Records of the form: 1193322267.954654 ? 10.0.1.195 64.233.171.19
        // https 49305 443 tcp ? ? S1 X

        NetSensorSession nss = new NetSensorSession();
        nss.setInitialString(line);
        nss.setSensorID(sensor);

        nss.setTypeID(typeID);
        nss.setTypeName(typeName);
        String[] tokens = line.split(" ");

        // This next block for testing only, old data did not have an ID and
        // stride
        // This block allows for backward compatibility
        int idx = tokens[0].indexOf("-");
        if (idx == -1) {
            // No ID, create a bogus one for testing only
            line = "1234-567890 " + line;
            nss.setInitialString(line);
            nss.setSensorID(sensor);

            tokens = line.split(" ");
        }

        String idStr = tokens[0];
        String[] idTokens = idStr.split("-");
        nss.strideID = Long.parseLong(idTokens[0]);
        nss.recID = Long.parseLong(idTokens[1]);

        String start = tokens[1];
        String[] startTokens = start.split("\\.");
        long millis = Long.parseLong(startTokens[0]) * 1000;
        millis += Double.parseDouble("0." + startTokens[1]) * 1000.0;

        nss.setStartTS(new Timestamp(millis));

        boolean testing = false;
        if (testing) {
            Timestamp ts = nss.getTimestamp();
            String tsStr = ts.toString();
            if (ts.before(Date.valueOf("1999-01-01"))) {
                tsStr = "2007" + tsStr.substring(4);
            } else if (ts.before(Date.valueOf("2000-01-01"))) {
                tsStr = "2008" + tsStr.substring(4);
            } else if (ts.before(Date.valueOf("2001-01-01"))) {
                tsStr = "2009" + tsStr.substring(4);
            }
            nss.setTimestamp(Timestamp.valueOf(tsStr));
            millis = nss.getTimestamp().getTime();
        }

        testing = true;
        if (testing) {
            millis = System.currentTimeMillis();
            nss.setStartTS(new Timestamp(millis));
        }
        String duration = tokens[2];
        if (!duration.equals("?")) {
            nss.duration = Double.parseDouble(tokens[2]);
            millis += nss.duration * 1000.0;
        }
        nss.setEndTS(new Timestamp(millis));
        

        nss.setSrcIP(NetFSEUtil.convertIPtoLong(tokens[3]));
        nss.setDstIP(NetFSEUtil.convertIPtoLong(tokens[4]));
        nss.appProto = tokens[5];
        nss.srcPort = Integer.parseInt(tokens[6]);
        nss.dstPort = Integer.parseInt(tokens[7]);
        nss.proto = NetFSEUtil.getProtocolValue(tokens[8]);
        if (!tokens[9].equals("?")) {
            nss.srcBytes = Long.parseLong(tokens[9]);
        } else
            nss.srcBytes = -1;
        if (!tokens[10].equals("?")) {
            nss.dstBytes = Long.parseLong(tokens[10]);
        } else
            nss.dstBytes = -1;

        nss.stateStr = tokens[11];
        try {
            nss.state = Integer.parseInt(nss.stateStr);
        } catch (Exception e) {
            try {
                nss.state = NetFSE.netSensorStates.getID(nss.stateStr);
            } catch (NullPointerException npe) {

            }
        }
        nss.flags = tokens[12];
        if (tokens.length > 13) {
            nss.tag = tokens[13];
        }

        // if (nss.dstBytes == -1 && nss.srcBytes == -1)
        // return null;

        if (nss.duration == -1.0)
            return null;

        return nss; // The record was sucessfully parsed, return it
    }

    @Override
    public NetFSERecord generate() {
        return new NetSensorSession();
    }

}
